package com.qd.controllers.user;

import net.paoding.rose.web.Invocation;
import net.paoding.rose.web.annotation.IfParamExists;
import net.paoding.rose.web.annotation.Param;
import net.paoding.rose.web.annotation.Path;
import net.paoding.rose.web.annotation.rest.Get;
import net.paoding.rose.web.annotation.rest.Post;
import net.paoding.rose.web.portal.Pipe;
import net.paoding.rose.web.portal.Portal;
import net.paoding.rose.web.portal.Window;
import net.paoding.rose.web.var.Flash;
import net.sf.json.JSONObject;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;

import com.qd.model.Tao;
import com.qd.test.model.Test;
import com.qd.test.service.TestService;
import com.qd.user.model.ShardUser;
import com.qd.user.service.ShardUserService;
import com.qd.validators.NotBlank;

/**
 * @author taomk
 * @version 1.0
 * @since 2014/9/16 17:50
 */
@Path("")
public class UserController {

	@Autowired
	private TestService testService;

	@Autowired
	private ShardUserService shardUserService;

	public String test() {
		// 返回@开始的字符串，表示将紧跟@之后的字符串显示在页面上
		return "@" + new java.util.Date();
	}

	public String velocity() {
		// 返回一个普通字符串，表示要从webapp/views/目录下找第一个以user-velocity.开始的页面
		// 运行本程序时，请在webapp/views/目录下创建一个名为user-velocity.vm的文件，写上写文本字符
		return "user-velocity";
	}

	public String jsp() {
		// 在webapp/views/目录下创建user-jsp.jsp的文件即可 (UTF-8的)。
		return "user-jsp";
	}

	public String render(Invocation inv) {
		// 在vm/jsp中可以使用$now渲染这个值
		inv.addModel("now", new java.util.Date());
		// 在vm/jsp中可以使用$user.id, $user.name渲染user的值
		ShardUser user = new ShardUser();
		user.setId(1);
		user.setName("taomk");
		inv.addModel("user", user);
		return "user-render";
	}

	public String redirect() {
		// 以r:开始表示重定向
		return "r:/user/test"; // 或 r:http://127.0.0.1/user/test
	}

	public String forward() {
		// 大多数情况下，以/开始即是转发(除非存在webapp/user/test文件)
		return "/user/test";
	}

	public String forward2() {
		// a:表示转发到同一个控制器的acton方法forward()
		return "a:forward";
	}

	public String forward3() {
		// f:可以转发到同一个应用的action方法
		return "f:forward";
	}

	@Get("list-by-group")
	public String listByGroup(@Param("groupId") String groupId) {
		return "@" + groupId;
	}

	@Get("list-by-group-{groupId}")
	public String listByGroup2(@Param("groupId") String groupId) {
		return "@string-" + groupId;
	}

	@Get("list-by-group-{groupId:\\d+}")
	public String listByGroup3(@Param("groupId") int groupId) {
		return "@int-" + groupId;
	}

	@Get("list-by-group-n{groupId:\\d+}")
	public String listByGroup4(@Param("groupId") int groupId) {
		return "@int-" + groupId;
	}

	public String param1(@Param("name") String name) {
		return "@" + name;
	}

	public String param2(Invocation inv) {
		return "@" + inv.getRequest().getParameter("name");
	}

	@Get("param3/{name}")
	public String param3(Invocation inv, @Param("name") String name) {
		// request.getParameter()也能获取@ReqMapping中定义的参数
		return "@method.name=" + name + "; request.param.name=" + inv.getRequest().getParameter("name");
	}

	public String array(@Param("id") int[] idArray) {
		return "@" + Arrays.toString(idArray);
	}

	public String keyOfMap(@Param("map") Map<Integer, String> map) {
		return "@" + Arrays.toString(map.keySet().toArray(new Integer[0]));
	}

	public String valueOfMap(@Param("map") Map<Integer, String> map) {
		return "@" + Arrays.toString(map.values().toArray(new String[0]));
	}

	public String map(@Param("map") Map<Integer, String> map) {
		StringBuilder sb = new StringBuilder();
		for (Map.Entry<Integer, String> entry : map.entrySet()) {
			sb.append(entry.getKey()).append("=").append(entry.getValue()).append("<br>");
		}
		return "@" + sb;
	}

	@Post("post")
	public String post(ShardUser user) {
		return "@" + user.getId() + "=" + user.getName();
	}

	@Post("post2")
	public String post2(ShardUser user) {
		return "@" + user.getId() + "; level.id=" + user.getLevel().getId();
	}

	public Object json(@Param("id") String id) {
		JSONObject json = new JSONObject();
		json.put("id", id);
		json.put("name", "rose");
		json.put("text", "json");
		// rose将调用json.toString()渲染
		return json;
	}

	// 把JSONObject放到方法中，Rose将帮忙创建实例
	public Object json2(JSONObject json, @Param("id") String id) {
		json.put("id", id);
		json.put("name", "rose");
		json.put("text", "json2");
		// rose将调用json.toString()渲染
		return json;
	}

	public Object xml(Invocation inv) {
		ShardUser user = new ShardUser();
		user.setId(1);
		user.setName("rose");
		inv.addModel("user", user);
		// rose将调用user-xml.xml或.vm或.jsp渲染页面(按字母升序顺序优先: jsp, vm, xml)
		// 使用user-xml.xml的，默认contentType是text/xml;charset=UTF-8，语法同velocity
		// 使用user-xml.jsp或user-xml.vm的可在本方法中标注@HttpFeatures(contentType="xxx")改变
		// jsp的也可通过<%@ page contentType="text/html;charset=UTF-8" %>改变
		return "user-xml";
	}

	public String param(Tao tao) throws Exception {
		return "@hello world:" + tao.getFirst() + ":" + tao.getSecond();
	}

	public String notBlank(@NotBlank @Param("messages") String messages) throws Exception {
		return "@hello world: notBlank " + messages;
	}

	public String flash1(Flash flash) {
		flash.add("msg", "修改成功！");
		return "r:/user/flash2";
	}

	public String flash2(Invocation inv, Flash flash) {
		inv.addModel("info", flash.get("msg"));
		return "flash";
	}

	// 设置@PortalSetting(timeout = 100)表示最多等待各个窗口100ms(包括window的页面渲染耗费时间)
	// 在主控控制方法上声明Portal参数即表示这个页面是portal，就这样!
	public String portal(Portal portal) {
		// 使用addWindow向这个portal页面加入各种子信息(我们成为窗口)
		portal.addWindow("p1", "/user/portal1");
		// 第一个参数是用于标识该窗口，使得portal页面中可以引用到这个窗口的html
		// 第二个参数表示这个窗口的地址(可以包含参数)，这个地址等价于forward的地址(也就是这里只要能forward的地址都可以，无论是否是rose框架的，甚至可以是一个jsp页面)
		portal.addWindow("p2", "/user/portal2");
		return "portal";
	}

	public String portal1(Invocation inv) {
		return "@this is portal1";
	}

	public String portal2(Invocation inv, Window window) {
		return "@this is portal2";
	}

	public String pipe(Pipe pipe) {
		pipe.addWindow("p1", "/user/pipe1");
		pipe.addWindow("p2", "/user/pipe2");
		return "pipe";
	}

	public String pipe1() {
		return "@this is pipe1";
	}

	public String pipe2() {
		return "@this is pipe2";
	}

	// 接收name为"file"的input上传上来的文件
	// MultipartFile是一个Spring类
	public String upload(@Param("file") MultipartFile file) {
		// MultiPartFile提供了getName(), getInputStream(), transferTo()等方法可以方便使用
		return "@ok-"+ file.getName();
	}

	// 接收name以"file"开始的input上传上来的所有文件
	// 接收名字为file1、file2等等的
	// files可以是一个数组或者List
	public String multiUpload(@Param("file") MultipartFile[] files) {
		return "@ok-" + Arrays.toString(files);
	}

	// 接收所有文件
	// 不声明@Param
	// files可以是一个数组或者List
	public String uploadAll(MultipartFile[] files) {
		return "@ok-" + Arrays.toString(files);
	}

	// 不声明@Param
	// 如果不声明为数组或List，只是一个MultipartFile,则取"第一个"上传的文件(特别适合于只上传一个文件的情况)
	public String uploadFirst(MultipartFile file) {
		return "@ok-" + file.getName();
	}

	// 接收名字为audio、video的input上传上来的文件
	public String upload(@Param("audio") MultipartFile audio, @Param("video") MultipartFile video) {
		return "@ok-";
	}

	// 接收名字为audio、video开始的input上传上来的所有文件
	public String upload(@Param("audio") MultipartFile[] audio, @Param("video") MultipartFile[] video) {
		return "@ok-";
	}

	// 接收名字为audio的input上传上来的文件，以及以video开始的input上传上来的所有文件
	public String upload(@Param("audio") MultipartFile audio,@Param("video") MultipartFile[] video) {
		return "@ok-";
	}

	@IfParamExists("msg")
	public String ifParamExists(@Param("msg") String msg) {
		return "@msg: " + msg;
	}

	@IfParamExists("msg=:[0-9]+")
	public String ifParamExists2(@Param("msg") String msg) {
		return "@msg=:[0-9]+: " + msg;
	}

	public String jadeTest() {
		return "@" + testService.getTest().toString();
	}

	@IfParamExists("name")
	public String insertTest(@Param("name") String name) {
		Test test = new Test();
		test.setMsg(name);
		return "@insert id = " + testService.insertTest(test);
	}

	public String findAllShardUsers() {
		StringBuilder sb = new StringBuilder();
		List<ShardUser> userList = shardUserService.findAll();

		for (ShardUser user : userList) {

			sb.append(user.toString()).append("<br>");
		}
		return "@" + sb.toString();
	}

	@IfParamExists("name")
	public String addShardUserByName(@Param("name") String name) {
		ShardUser user = new ShardUser();
		user.setName(name);

		int id = shardUserService.add(user);
		return "@insert user id = " + id;
	}

	@IfParamExists("name")
	public String findShardUserByName(@Param("name") String name) {

		ShardUser user = shardUserService.findByName(name);
		return "@findShardUserByName = " + user.toString();
	}
}
